/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.ui.rich.full.controller;

import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import br.ufmg.dees.insane.commons.controller.Controller;
import br.ufmg.dees.insane.commons.view.DrawingArea;
import br.ufmg.dees.insane.draw.AxisDraw;
import br.ufmg.dees.insane.draw.Draw;
import br.ufmg.dees.insane.draw.GridArrowDraw;
import br.ufmg.dees.insane.draw.GridDisplaceDraw;
import br.ufmg.dees.insane.draw.GridLiberationDraw;
import br.ufmg.dees.insane.draw.GridLineArrowDraw;
import br.ufmg.dees.insane.draw.GridReactionDraw;
import br.ufmg.dees.insane.draw.LineDraw;
import br.ufmg.dees.insane.draw.PointDraw;
import br.ufmg.dees.insane.draw.StringDraw;
import br.ufmg.dees.insane.model.Model;
import br.ufmg.dees.insane.model.disc.element.Element;
import br.ufmg.dees.insane.model.disc.element.FrameElement;
import br.ufmg.dees.insane.model.disc.element.force.ElementForce;
import br.ufmg.dees.insane.model.disc.fem.FemModel;
import br.ufmg.dees.insane.model.disc.node.Node;
import br.ufmg.dees.insane.model.disc.pointforce.PointForce;
import br.ufmg.dees.insane.ui.rich.full.InsaneInternalInterface;
import br.ufmg.dees.insane.util.IPoint3d;

/**
 * @author Fonseca, Flavio & Pitangueira, Roque
 * @since July 2004
 */
public class GridReactionsController implements Controller {
	
	protected InsaneInternalInterface parent;
	protected Model model;
	protected FemModel fmodel;
	protected DrawingArea da;
	protected ArrayList<Object> selection = new ArrayList<Object>();
	
	protected ArrayList<Draw> nodes = new ArrayList<Draw>();
	protected ArrayList<Draw> elements = new ArrayList<Draw>();
	
	protected ArrayList<Draw> reactions = new ArrayList<Draw>();
	protected ArrayList<Draw> nodalLoads = new ArrayList<Draw>();
	protected ArrayList<Draw> displaces = new ArrayList<Draw>();
	
	protected ArrayList<Draw> localAxis = new ArrayList<Draw>();
	protected ArrayList<Draw> concForces = new ArrayList<Draw>();
	protected ArrayList<Draw> concForcesPoints = new ArrayList<Draw>();
	protected ArrayList<Draw> liberations = new ArrayList<Draw>();
	protected ArrayList<Draw> preStrains = new ArrayList<Draw>();
	protected ArrayList<Draw> distForces = new ArrayList<Draw>();
	protected ArrayList<Draw> tempChanges = new ArrayList<Draw>();
	protected ArrayList<Draw> iniEqForces = new ArrayList<Draw>();
	protected ArrayList<Draw> elasticConnections = new ArrayList<Draw>();
	
//*****************************************************************************
	
    /** The constructor method. */
    public GridReactionsController(Model model, DrawingArea da) {
		this.model = model;
        this.da = da;
        this.fmodel = this.model.getDiscreteModel();
    }
	
//*****************************************************************************
	
	public void setParent(InsaneInternalInterface par) {
		this.parent = par;
	}
	
//*****************************************************************************
	
    public void draw(Graphics2D g) {
        
		double nodeScale = model.getState().nodeScale;
		double supportScale = model.getState().supportScale;
		double loadScale = model.getState().loadScale;
		double displaceScale = model.getState().displaceScale;
		double concForcePointScale = model.getState().concForcePointScale;
		double preStrainsScale = model.getState().preStrainsScale;
		double iniEqForceScale = model.getState().iniEqForceScale;
		double reactionsScale = model.getState().reactionsScale;
		
        g.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
		
		Draw draw;
		Node no;
		
		//Draws global axis if selected
		if (model.getState().getViewGlobalAxis()) {
			g.setColor(model.getState().globalAxisColor);
			draw = new AxisDraw();
			((AxisDraw)draw).setLabel1("X");
			((AxisDraw)draw).setLabel2("Z");
			draw.setLocation(new Point(10, da.getHeight()-10));
			draw.draw(g);
		}
		
		//Draws elements
		ListIterator lns = elements.listIterator();
		while(lns.hasNext()) {
			g.setColor(model.getState().lineColor);
			draw = (Draw)lns.next();
			draw.draw(g);
		}
		
		//Draws local axis
		if (model.getState().getViewLocalAxis()) {
			ListIterator la = localAxis.listIterator();
			while(la.hasNext()) {
				g.setColor(model.getState().localAxisColor);
				draw = (Draw)la.next();
				draw.draw(g);
			}
		}
		
		//Draws liberations
		g.setColor(model.getState().supportColor);
		ListIterator libs = liberations.listIterator();
		while(libs.hasNext()) {
			draw = (Draw)libs.next();
			draw.setScale(supportScale);
			draw.draw(g);
		}
		
		//Draws initial equivalent nodal forces
		g.setColor(model.getState().iniEqForceColor);
		ListIterator ies = iniEqForces.listIterator();
		while(ies.hasNext()) {
			draw = (Draw)ies.next();
			draw.setScale(iniEqForceScale);
			draw.draw(g);
		}
		
		//Draws temperature changes
		g.setColor(model.getState().tempChangeColor);
		ListIterator tcs = tempChanges.listIterator();
		while(tcs.hasNext()) {
			draw = (Draw)tcs.next();
			draw.draw(g);
		}
		
		//Draws prescribed displacements
		g.setColor(model.getState().displaceColor);
		ListIterator dds = displaces.listIterator();
		while(dds.hasNext()) {
			draw = (Draw)dds.next();
			no = (Node)draw.getRepresents();
			IPoint3d p3 = no.getCoord();
			draw.setLocation(da.getViewPoint( new Point2D.Double(p3.x, p3.z) ));
			draw.setScale(displaceScale);
			draw.draw(g);
		}
		
		//Draws pre-strains
		g.setColor(model.getState().preStrainsColor);
		ListIterator pss = preStrains.listIterator();
		while(pss.hasNext()) {
			draw = (Draw)pss.next();
			draw.setScale(preStrainsScale);
			draw.draw(g);
		}
		
		//Draws nodal loads
		g.setColor(model.getState().loadColor);
		ListIterator nls = nodalLoads.listIterator();
		while(nls.hasNext()) {
			draw = (Draw)nls.next();
			no = (Node)draw.getRepresents();
			IPoint3d p3 = no.getCoord();
			draw.setLocation(da.getViewPoint( new Point2D.Double(p3.x, p3.z)));
			draw.setScale(loadScale);
			draw.draw(g);
		}
		
		//Draws nodes
		g.setColor(model.getState().pointColor);
		ListIterator pts = nodes.listIterator();
		while(pts.hasNext()) {
			draw = (Draw)pts.next();
			no = (Node)draw.getRepresents();
			if (model.getState().getViewNodeLabel())
				draw.setLabel(no.getLabel());
			else draw.setLabel("");
			if (model.getDiscreteModel().getGlobalAnalysisModel().getType().equals("PlaneTruss")){
				g.setColor(model.getState().pointColor);
				draw.setScale(nodeScale*2);
				draw.draw(g);
				Draw draw2 = (Draw)draw.clone();
				g.setColor(model.getState().getBackground());
				draw2.setScale(nodeScale*1);
				draw2.setSelected(false);
				draw2.setSelectable(false);
				draw2.draw(g);
			} else {
				draw.setScale(nodeScale*1);
				draw.draw(g);
			}
		}
		
		//Draws concentrated forces
		g.setColor(model.getState().loadColor);
		ListIterator cfs = concForces.listIterator();
		while(cfs.hasNext()) {
			draw = (Draw)cfs.next();
			draw.setScale(loadScale);
			draw.draw(g);
		}
		
		//Draws concentrated forces points
		g.setColor(model.getState().concForcePointColor);
		ListIterator cfps = concForcesPoints.listIterator();
		while(cfps.hasNext()) {
			draw = (Draw)cfps.next();
			draw.setScale(concForcePointScale);
			draw.draw(g);
		}
		
		//Draws distributed forces
		g.setColor(model.getState().distributedLoadColor);
		ListIterator dfs = distForces.listIterator();
		while(dfs.hasNext()) {
			draw = (Draw)dfs.next();
			draw.setScale(loadScale);
			draw.draw(g);
		}
		
		//Draws reactions
		g.setColor(model.getState().reactionsColor);
		ListIterator rea = reactions.listIterator();
		while(rea.hasNext()) {
			draw = (Draw)rea.next();
			no = (Node)draw.getRepresents();
			IPoint3d p3 = no.getCoord();
			draw.setLocation(da.getViewPoint( new Point2D.Double(p3.x, p3.z) ));
			draw.setScale(reactionsScale);
			draw.draw(g);
		}
		
	}
	
//*****************************************************************************
	
    public void fit() {
        
        //Calculating bounds
        if (nodes.size() >= 2){
            Point leftUp = new Point();
            Point rightDown = new Point();
            PointDraw po;
            ListIterator pts = nodes.listIterator();
            po = (PointDraw)pts.next();
            leftUp.x = po.getLocation().x;
            leftUp.y = po.getLocation().y;
            rightDown.x = po.getLocation().x;
            rightDown.y = po.getLocation().y;
            while (pts.hasNext()){
                po = (PointDraw)pts.next();
                if (po.getLocation().x < leftUp.x){
                    leftUp.x = po.getLocation().x;
                }
                if (po.getLocation().x > rightDown.x){
                    rightDown.x = po.getLocation().x;
                }
                if (po.getLocation().y < leftUp.y){
                    leftUp.y = po.getLocation().y;
                }
                if (po.getLocation().y > rightDown.y){
                    rightDown.y = po.getLocation().y;
                }
            }
			
            //Adding some border
            leftUp.x = leftUp.x - 15;
            leftUp.y = leftUp.y - 15;
            rightDown.x = rightDown.x + 15;
            rightDown.y = rightDown.y + 15;
            
            Point2D p1 = da.getWorldPoint(leftUp);
            Point2D p2 = da.getWorldPoint(rightDown);
            Rectangle2D r = new Rectangle2D.Double(p1.getX(), p2.getY(), p2.getX(), p1.getY());
            
			da.setZoom(r);
        }
    }
	
//*****************************************************************************
	
    public void add(Object obj) {
		
		if (obj instanceof GridDisplaceDraw) {
			GridDisplaceDraw dd = (GridDisplaceDraw)obj;
			Node no = (Node)dd.getRepresents();
			IPoint3d p3 = no.getCoord();
			dd.setLocation( da.getViewPoint(new Point2D.Double(p3.x, p3.z)) );
			displaces.add(dd);
		}
		
		if (obj instanceof GridArrowDraw) {
			GridArrowDraw a = (GridArrowDraw)obj;
			
			Object obj2 = a.getRepresents();
			if (obj2 instanceof Node) {
				Node no = (Node)a.getRepresents();
				if (no != null){
					IPoint3d p3 = no.getCoord();
					a.setLocation(da.getViewPoint( new Point2D.Double(p3.x, p3.z) ));
					nodalLoads.add(a);
				}
			}
			else if (obj2 instanceof FrameElement) {
				concForces.add(a);
			}
		}
		
	}
	
//*****************************************************************************
	
    public boolean contains(Point2D po) {
        Point p = da.getViewPoint(po);
        Draw draw;
        
        ListIterator pts = nodes.listIterator();
        while(pts.hasNext()) {
            draw = (Draw)pts.next();
            if (draw.contains(p)) {
                return true;
            }
        }
		ListIterator lns = nodes.listIterator();
		while(lns.hasNext()) {
			draw = (Draw)lns.next();
			if (draw.contains(p)) {
				return true;
			}
		}
        return false;
    }
	
//*****************************************************************************
	
    public boolean contains(Line2D l) {
        Point  p1 = da.getViewPoint(l.getP1());
        Point  p2 = da.getViewPoint(l.getP2());
        Draw draw;
        
        ListIterator lns = elements.listIterator();
        while(lns.hasNext()) {
            draw = (Draw)lns.next();
            if (draw.contains(p1) && draw.contains(p2)) {
                return true;
            }
        }
        
        return false;
    }
	
//*****************************************************************************
	
    public Point pick(Point p) {
        
        Draw draw;
		
        ListIterator pts = nodes.listIterator();
        while(pts.hasNext()) {
            draw = (Draw)pts.next();
            if (draw.contains(p)) {
                return draw.getLocation();
            }
        }
		ListIterator lns = elements.listIterator();
		while(lns.hasNext()) {
			draw = (Draw)lns.next();
			if (draw.contains(p)) {
				return draw.getLocation();
			}
		}
        return p;
    }
	
//*****************************************************************************
	
    public void remove(Object obj) {
        /*
		if (obj instanceof Node) {
            fmodel.remove((Node)obj);
        }
        if (obj instanceof Element) {
            fmodel.remove((Element)obj);
        }
        if (obj instanceof Material) {
            fmodel.remove((Material)obj);
        }
        if (obj instanceof CrossSection) {
            fmodel.remove((CrossSection)obj);
        }
		if (obj instanceof AnalysisModel) {
            fmodel.remove((AnalysisModel)obj);
        }
		this.compose();
		*/
		
    }
	
//*****************************************************************************
	
    public List removeSelection() {
        
        ArrayList<Object> sel = new ArrayList<Object>();
		PointDraw pd;
        LineDraw ld;
        int index;
        
        ListIterator pts = nodes.listIterator();
        while(pts.hasNext()) {
            pd = (PointDraw)pts.next();
            if (pd.isSelected()) {
				Node p = (Node)pd.getRepresents();
				index = selection.indexOf(pd.getRepresents());
				selection.remove(index);
                fmodel.remove(p);
                sel.add(p);
            }
        }
		ListIterator lns = elements.listIterator();
		while(lns.hasNext()) {
			ld = (LineDraw)lns.next();
			if (ld.isSelected()){
				Element l = (Element)ld.getRepresents();
				index = selection.indexOf(ld.getRepresents());
				selection.remove(index);
				fmodel.remove(l);
				sel.add(l);
			}
		}
		this.compose();
		
		return sel;
		
    }
    
//*****************************************************************************
	
    public void removeAll() {
        nodes.clear();
		elements.clear();
		
		reactions.clear();
		nodalLoads.clear();
		displaces.clear();
		
		localAxis.clear();
		concForces.clear();
		concForcesPoints.clear();
		liberations.clear();
		preStrains.clear();
		distForces.clear();
		tempChanges.clear();
		iniEqForces.clear();
		elasticConnections.clear();
		
    }
	
//*****************************************************************************
	
	public void unSelectPoints() {
        Draw draw;
        
        ListIterator pts = nodes.listIterator();
        while(pts.hasNext()) {
            draw = (Draw)pts.next();
            draw.setSelected(false);
        }
	}
	
//*****************************************************************************
	
    public ArrayList getSelection() {
        return selection;
    }
	
//*****************************************************************************
	
    public Object get(Point2D po) {
		Point location = da.getViewPoint(po);
        Draw draw;
        
        ListIterator pts = nodes.listIterator();
        while(pts.hasNext()) {
            draw = (Draw)pts.next();
            if (draw.contains(location)) {
                return draw.getRepresents();
            }
        }
		ListIterator lns = elements.listIterator();
		while(lns.hasNext()) {
			draw = (Draw)lns.next();
			if (draw.contains(location)){
				return draw.getRepresents();
			}
		}
		
        return null;
    }
    
//*****************************************************************************
	
    public boolean isSelected() {
        Draw draw;
        
        ListIterator pts = nodes.listIterator();
        while(pts.hasNext()) {
            draw = (Draw)pts.next();
            if (draw.isSelected()) {
                return true;
            }
        }
		ListIterator lns = elements.listIterator();
		while(lns.hasNext()) {
			draw = (Draw)lns.next();
			if (draw.isSelected()){
				return true;
			}
		}
		
		return false;
	}
	
//*****************************************************************************
	
	public void compose() {
		
		this.removeAll();
		
		//Filling the "nodes", "reactions" and "nodalLoads" lists
		ListIterator femnodes = fmodel.getNodesList().listIterator();
		
		Node node;
		Point2D po;
		Point p;
		while (femnodes.hasNext()) {
			node = (Node)femnodes.next();
			po = new Point2D.Double(node.getCoord().x, node.getCoord().z);
			p = da.getViewPoint(po);
			nodes.add(new PointDraw(p, node));
			
			//Adding inelastic reactions
			//Fy reactions
			if (node.getReaction(1) != 0) {
				Draw draw = new GridReactionDraw.Out();
				draw.setRepresents(node);
				((GridReactionDraw)draw).setValue(node.getReaction(1));
				//draw.setLabel(String.valueOf(node.getReaction(1)));
				reactions.add(draw);
			}
			//Mx loads
			if (node.getReaction(3) != 0) {
				Draw draw = new GridReactionDraw.AntiClockwise();
				draw.setRepresents(node);
				((GridReactionDraw)draw).setValue(node.getReaction(3));
				draw.setAngle(node.getAngle()*Math.PI/180);
				//draw.setLabel(String.valueOf(node.getReaction(3)));
				reactions.add(draw);
			}
			//Mz loads
			if (node.getReaction(5) != 0) {
				Draw draw = new GridReactionDraw.AntiClockwise();
				draw.setRepresents(node);
				((GridReactionDraw)draw).setValue(node.getReaction(5));
				draw.setAngle(Math.toRadians(90) + node.getAngle()*Math.PI/180);
				//draw.setLabel(String.valueOf(node.getReaction(5)));
				reactions.add(draw);
			}
			//End of adding inelastic reactions
			
			//Adding elastic reactions
			//Fy reactions
			if (node.getSpring(1) != 0) {
				Draw draw = new GridReactionDraw.Out();
				draw.setRepresents(node);
				((GridReactionDraw)draw).setValue(-node.getDisplacement(1)*node.getSpring(1));
				//draw.setLabel(String.valueOf(node.getReaction(1)));
				reactions.add(draw);
			}
			//Mx loads
			if (node.getSpring(3) != 0) {
				Draw draw = new GridReactionDraw.Out();
				draw.setRepresents(node);
				((GridReactionDraw)draw).setValue(-node.getDisplacement(3)*node.getSpring(3));
				draw.setAngle(node.getAngle()*Math.PI/180);
				//draw.setLabel(String.valueOf(node.getReaction(3)));
				reactions.add(draw);
			}
			//Mz loads
			if (node.getSpring(5) != 0) {
				Draw draw = new GridReactionDraw.AntiClockwise();
				draw.setRepresents(node);
				((GridReactionDraw)draw).setValue(-node.getDisplacement(5)*node.getSpring(5));
				draw.setAngle(Math.toRadians(90) + node.getAngle()*Math.PI/180);
				//draw.setLabel(String.valueOf(node.getReaction(5)));
				reactions.add(draw);
			}
			//End of adding elastic reactions
			
			//Adding nodal loads
			//Fy loads
			if (node.getForce(1) != 0) {
				Draw draw = new GridArrowDraw.Out();
				draw.setRepresents(node);
				((GridArrowDraw)draw).setValue(node.getForce(1));
				//draw.setLabel(String.valueOf(node.getForce(1)));
				this.add(draw);
			}
			//Mx loads
			if (node.getForce(3) != 0) {
				Draw draw = new GridArrowDraw.AntiClockwise();
				draw.setRepresents(node);
				((GridArrowDraw)draw).setValue(node.getForce(3));
				draw.setAngle(node.getAngle()*Math.PI/180);
				//draw.setLabel(String.valueOf(node.getForce(1)));
				this.add(draw);
			}
			//Mz loads
			if (node.getForce(5) != 0) {
				Draw draw = new GridArrowDraw.AntiClockwise();
				draw.setRepresents(node);
				((GridArrowDraw)draw).setValue(node.getForce(5));
				draw.setAngle(Math.toRadians(90) + node.getAngle()*Math.PI/180);
				//draw.setLabel(String.valueOf(node.getForce(5)));
				this.add(draw);
			}
			//End of adding nodalLoads
			
			//Adding prescribed displacement
			double Ddy = node.getPreDisplacement(1);
			double Drx = node.getPreDisplacement(3);
			double Drz = node.getPreDisplacement(5);
			if (Ddy!=0) {
				Draw draw = new GridDisplaceDraw.Linear();
				draw.setRepresents(node);
				((GridDisplaceDraw)draw).setValue(Ddy);
				this.add(draw);
			}
			if (Drx!=0) {
				Draw draw = new GridDisplaceDraw.Angular();
				draw.setRepresents(node);
				draw.setAngle(Math.toRadians(node.getAngle()));
				((GridDisplaceDraw)draw).setValue(Drx);
				this.add(draw);
			}
			if (Drz!=0) {
				Draw draw = new GridDisplaceDraw.Angular();
				draw.setRepresents(node);
				draw.setAngle(Math.toRadians(node.getAngle() +90));
				((GridDisplaceDraw)draw).setValue(Drz);
				this.add(draw);
			}//end of add prescribed displacement
		}
		
		//Filling the "elements", "localAxis", "liberations", "concForces", "concForcesPoints",
		// "preStrains", "distForces", "tempChanges", "iniEqForces" and "elasticConnections" lists
		ListIterator elms = fmodel.getElementsList().listIterator();
		FrameElement elm;
		Point p1;
		Point p2;
		while (elms.hasNext()) {
			elm = (FrameElement)elms.next();
			node = elm.getInitialNode();
			po = new Point2D.Double(node.getCoord().x, node.getCoord().z);
			p1 = da.getViewPoint(po);
			node = elm.getFinalNode();
			po = new Point2D.Double(node.getCoord().x, node.getCoord().z);
			p2 = da.getViewPoint(po);
			elements.add(new LineDraw(p1, p2, elm));
			
			//Setting the variables in (initial node) and fn (final node)
			Node in = elm.getInitialNode();
			Node fn = elm.getFinalNode();
			
			//Calculating the angle between local axis and global axis and its sine and cosine
			double elmAngle = 0;
			Point2D in2d = new Point2D.Double(in.getCoord().x, in.getCoord().z);
			Point2D fn2d = new Point2D.Double(fn.getCoord().x, fn.getCoord().z);
			in2d = da.getViewPoint(in2d);
			fn2d = da.getViewPoint(fn2d);
			
			if (fn.getCoord().x > in.getCoord().x) {
				elmAngle = -Math.atan((fn2d.getY() - in2d.getY()) / (fn2d.getX() - in2d.getX()));
			} else if (fn.getCoord().x < in.getCoord().x) {
				elmAngle = -Math.atan((fn2d.getY() - in2d.getY()) / (fn2d.getX() - in2d.getX())) + Math.toRadians(180);
			} else if ((fn.getCoord().x==in.getCoord().x) && (fn.getCoord().z>in.getCoord().z)) {
				elmAngle = Math.toRadians(90);
			} else if ((fn.getCoord().x==in.getCoord().x) && (fn.getCoord().z<in.getCoord().z)) {
				elmAngle = Math.toRadians(-90);
			}
			
			//Adding Local Axis
			Draw draw2 = new AxisDraw();
			draw2.setRepresents(elm);
			draw2.setAngle(elmAngle);
			draw2.setLocation(p1);
			((AxisDraw)draw2).setLabel1("X");
			((AxisDraw)draw2).setLabel2("Z");
			localAxis.add(draw2);
			
			//Adding liberations
			//Dy1 liberation
			if (elm.getLiberation(1) && !elm.getLiberation(3) && !elm.getLiberation(5)){
				Draw draw = new GridLiberationDraw.Y();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle);
				draw.setLocation(p1);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Rx1 liberation
			if (!elm.getLiberation(1) && elm.getLiberation(3) && !elm.getLiberation(5)){
				Draw draw = new GridLiberationDraw.X();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle);
				draw.setLocation(p1);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Rz1 liberation
			if (!elm.getLiberation(1) && !elm.getLiberation(3) && elm.getLiberation(5)){
				Draw draw = new GridLiberationDraw.Z();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle);
				draw.setLocation(p1);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Dy1 and Rx1 liberation
			if (elm.getLiberation(1) && elm.getLiberation(3) && !elm.getLiberation(5)){
				Draw draw = new GridLiberationDraw.XY();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle);
				draw.setLocation(p1);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Dy1 and Rz1 liberation
			if (elm.getLiberation(1) && !elm.getLiberation(3) && elm.getLiberation(5)){
				Draw draw = new GridLiberationDraw.YZ();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle);
				draw.setLocation(p1);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Rx1 and Rz1 liberation
			if (!elm.getLiberation(1) && elm.getLiberation(3) && elm.getLiberation(5)){
				Draw draw = new GridLiberationDraw.XZ();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle);
				draw.setLocation(p1);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Dy1, Rx1 and Rz1 liberation
			if (elm.getLiberation(1) && elm.getLiberation(3) && elm.getLiberation(5)){
				Draw draw = new GridLiberationDraw.XYZ();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle);
				draw.setLocation(p1);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			
			//Dy2 liberation
			if (elm.getLiberation(7) && !elm.getLiberation(9) && !elm.getLiberation(11)){
				Draw draw = new GridLiberationDraw.Y();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle + Math.toRadians(180));
				draw.setLocation(p2);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Rx2 liberation
			if (!elm.getLiberation(7) && elm.getLiberation(9) && !elm.getLiberation(11)){
				Draw draw = new GridLiberationDraw.X();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle + Math.toRadians(180));
				draw.setLocation(p2);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Rz2 liberation
			if (!elm.getLiberation(7) && !elm.getLiberation(9) && elm.getLiberation(11)){
				Draw draw = new GridLiberationDraw.Z();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle + Math.toRadians(180));
				draw.setLocation(p2);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Dy2 and Rx2 liberation
			if (elm.getLiberation(7) && elm.getLiberation(9) && !elm.getLiberation(11)){
				Draw draw = new GridLiberationDraw.XY();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle + Math.toRadians(180));
				draw.setLocation(p2);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Dy2 and Rz2 liberation
			if (elm.getLiberation(7) && !elm.getLiberation(9) && elm.getLiberation(11)){
				Draw draw = new GridLiberationDraw.YZ();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle + Math.toRadians(180));
				draw.setLocation(p2);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Rx2 and Rz2 liberation
			if (!elm.getLiberation(7) && elm.getLiberation(9) && elm.getLiberation(11)){
				Draw draw = new GridLiberationDraw.XZ();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle + Math.toRadians(180));
				draw.setLocation(p2);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//Dy2, Rx2 and Rz2 liberation
			if (elm.getLiberation(7) && elm.getLiberation(9) && elm.getLiberation(11)){
				Draw draw = new GridLiberationDraw.XYZ();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle + Math.toRadians(180));
				draw.setLocation(p2);
				((GridLiberationDraw)draw).setModelState(model.getState());
				liberations.add(draw);
			}
			//End of adding liberations
			
			/*
			//Adding elastic connections
			if (elm.getMaterial() instanceof MSpring) {
				MSpring mat = (MSpring)elm.getMaterial();
			}
			//End of adding elastic connections
			*/
			
			//Adding concentrated forces
			ListIterator cf = elm.getElmPointForcesList().listIterator();
			while (cf.hasNext()) {
				PointForce force = (PointForce)cf.next();
				
				//Setting the application point of this concentrated force
				double cos2 = (fn.getCoord().x - in.getCoord().x) / elm.getLength();
				double sin2 = (fn.getCoord().z - in.getCoord().z) / elm.getLength();
				
				double d = force.getCoord().x;
				double x1 = in.getCoord().x + d*cos2;
				double z1 = in.getCoord().z + d*sin2;
				
				po = new Point2D.Double(x1, z1);
				p = da.getViewPoint(po);
				concForcesPoints.add(new PointDraw(p, elm));
				
				//Fy loads
				if (force.getForce(1) != 0) {
					Draw draw = new GridArrowDraw.Out();
					draw.setRepresents(elm);
					((GridArrowDraw)draw).setValue(force.getForce(1));
					draw.setLocation(da.getViewPoint(new Point2D.Double(x1, z1)));
					//draw.setLabel(String.valueOf(force.getForce(0)));
					concForces.add(draw);
				}
				//Mx loads
				if (force.getForce(3) != 0) {
					Draw draw = new GridArrowDraw.AntiClockwise();
					draw.setRepresents(elm);
					((GridArrowDraw)draw).setValue(force.getForce(3));
					//double forceAngle = elmAngle + Math.toRadians(90);
					//draw.setAngle(forceAngle);
					draw.setAngle(elmAngle);
					draw.setLocation(da.getViewPoint(new Point2D.Double(x1, z1)));
					//draw.setLabel(String.valueOf(force.getForce(1)));
					this.add(draw);
				}
				//Mz loads
				if (force.getForce(5) != 0) {
					Draw draw = new GridArrowDraw.AntiClockwise();
					draw.setRepresents(elm);
					((GridArrowDraw)draw).setValue(force.getForce(5));
					double forceAngle = elmAngle + Math.toRadians(90);
					draw.setAngle(forceAngle);
					draw.setLocation(da.getViewPoint(new Point2D.Double(x1, z1)));
					this.add(draw);
				}
			}//end of adding conc forces
			
			//Adding pre-strains
			if (elm.getElmPreDisplacement(1) != 0){
				Draw draw = new GridDisplaceDraw.Linear();
				draw.setRepresents(elm);
				draw.setLocation(p1);
				((GridDisplaceDraw)draw).setValue(elm.getElmPreDisplacement(1));
				preStrains.add(draw);
			}
			if (elm.getElmPreDisplacement(3) != 0){
				Draw draw = new GridDisplaceDraw.Angular();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle);
				draw.setLocation(p1);
				((GridDisplaceDraw)draw).setValue(elm.getElmPreDisplacement(3));
				preStrains.add(draw);
			}
			if (elm.getElmPreDisplacement(5) != 0){
				Draw draw = new GridDisplaceDraw.Angular();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle + Math.toRadians(90));
				draw.setLocation(p1);
				((GridDisplaceDraw)draw).setValue(elm.getElmPreDisplacement(5));
				preStrains.add(draw);
			}
			if (elm.getElmPreDisplacement(7) != 0){
				Draw draw = new GridDisplaceDraw.Linear();
				draw.setRepresents(elm);
				draw.setLocation(p2);
				((GridDisplaceDraw)draw).setValue(elm.getElmPreDisplacement(7));
				preStrains.add(draw);
			}
			if (elm.getElmPreDisplacement(9) != 0){
				Draw draw = new GridDisplaceDraw.Angular();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle);
				draw.setLocation(p2);
				((GridDisplaceDraw)draw).setValue(elm.getElmPreDisplacement(9));
				preStrains.add(draw);
			}
			if (elm.getElmPreDisplacement(11) != 0){
				Draw draw = new GridDisplaceDraw.Angular();
				draw.setRepresents(elm);
				draw.setAngle(elmAngle + Math.toRadians(90));
				draw.setLocation(p2);
				((GridDisplaceDraw)draw).setValue(elm.getElmPreDisplacement(11));
				preStrains.add(draw);
			}
			//end of adding pre-strains
			
			//Adding initial equivalent nodal forces
			if (elm.getInitialNodalForce(1) != 0) {
				Draw draw = new GridArrowDraw.Out();
				draw.setRepresents(elm);
				((GridArrowDraw)draw).setValue(elm.getInitialNodalForce(1));
				draw.setLocation(p1);
				iniEqForces.add(draw);
			}
			if (elm.getInitialNodalForce(3) != 0) {
				Draw draw = new GridArrowDraw.AntiClockwise();
				draw.setRepresents(elm);
				((GridArrowDraw)draw).setValue(elm.getInitialNodalForce(3));
				draw.setAngle(elmAngle);
				draw.setLocation(p1);
				iniEqForces.add(draw);
			}
			if (elm.getInitialNodalForce(5) != 0) {
				Draw draw = new GridArrowDraw.AntiClockwise();
				draw.setRepresents(elm);
				((GridArrowDraw)draw).setValue(elm.getInitialNodalForce(5));
				draw.setAngle(elmAngle + Math.toRadians(90));
				draw.setLocation(p1);
				iniEqForces.add(draw);
			}
			if (elm.getInitialNodalForce(7) != 0) {
				Draw draw = new GridArrowDraw.AntiClockwise();
				draw.setRepresents(elm);
				((GridArrowDraw)draw).setValue(elm.getInitialNodalForce(7));
				draw.setAngle(elmAngle);
				draw.setLocation(p2);
				iniEqForces.add(draw);
			}
			if (elm.getInitialNodalForce(9) != 0) {
				Draw draw = new GridArrowDraw.Out();
				draw.setRepresents(elm);
				((GridArrowDraw)draw).setValue(elm.getInitialNodalForce(9));
				draw.setAngle(elmAngle);
				draw.setLocation(p2);
				iniEqForces.add(draw);
			}
			if (elm.getInitialNodalForce(11) != 0) {
				Draw draw = new GridArrowDraw.AntiClockwise();
				draw.setRepresents(elm);
				((GridArrowDraw)draw).setValue(elm.getInitialNodalForce(11));
				draw.setAngle(elmAngle + Math.toRadians(90));
				draw.setLocation(p2);
				iniEqForces.add(draw);
			}
			//End of adding initial equivalent nodal forces
			
			//Adding temperature changes
			if (elm.getDeltaTemp(0) != 0) {
				Draw draw = new StringDraw();
				draw.setRepresents(elm);
				((StringDraw)draw).setString("Ts = " + String.valueOf(elm.getDeltaTemp(0)));
				int x = (int) ((p1.getX() + p2.getX())/2);
				int y = (int) ((p1.getY() + p2.getY())/2);
				draw.setAngle(elmAngle);
				((StringDraw)draw).setCentre(new Point(x, y));
				draw.setLocation(new Point(x, y-6));
				tempChanges.add(draw);
			}
			if (elm.getDeltaTemp(1) != 0) {
				Draw draw = new StringDraw();
				draw.setRepresents(elm);
				((StringDraw)draw).setString("Tn = " + String.valueOf(elm.getDeltaTemp(1)));
				int x = (int) ((p1.getX() + p2.getX())/2);
				int y = (int) ((p1.getY() + p2.getY())/2);
				draw.setAngle(elmAngle);
				((StringDraw)draw).setCentre(new Point(x, y));
				draw.setLocation(new Point(x, y+4));
				tempChanges.add(draw);
			}
			if (elm.getDeltaTemp(2) != 0) {
				Draw draw = new StringDraw();
				draw.setRepresents(elm);
				((StringDraw)draw).setString("Ti = " + String.valueOf(elm.getDeltaTemp(2)));
				int x = (int) ((p1.getX() + p2.getX())/2);
				int y = (int) ((p1.getY() + p2.getY())/2);
				draw.setAngle(elmAngle);
				((StringDraw)draw).setCentre(new Point(x, y));
				draw.setLocation(new Point(x, y+14));
				tempChanges.add(draw);
			}
			//End of adding temperature changes
			
			//Adding distributed loads
			ListIterator dfs = elm.getElmLineForcesList().listIterator();
			while (dfs.hasNext()) {
				ElementForce force = (ElementForce)dfs.next();
				
				//Setting the application points of this distributed force
				double cos2 = (fn.getCoord().x - in.getCoord().x) / elm.getLength();
				double sin2 = (fn.getCoord().z - in.getCoord().z) / elm.getLength();
				
				double d1 = ((PointForce)force.getPointForcesList().get(0)).getCoord().x;
				double d2 = ((PointForce)force.getPointForcesList().get(1)).getCoord().x;
				double x1 = in.getCoord().x + d1*cos2;
				double z1 = in.getCoord().z + d1*sin2;
				double x2 = in.getCoord().x + d2*cos2;
				double z2 = in.getCoord().z + d2*sin2;
				
				//Setting the values of a, b, axvalue, bxvalue, ayvalue and byvalue
				double a = ((PointForce)force.getPointForcesList().get(0)).getCoord().x;
				double b = ((PointForce)force.getPointForcesList().get(1)).getCoord().x;
				double axvalue = ((PointForce)force.getPointForcesList().get(0)).getForce(3);
				double bxvalue = ((PointForce)force.getPointForcesList().get(1)).getForce(3);
				double ayvalue = ((PointForce)force.getPointForcesList().get(0)).getForce(1);
				double byvalue = ((PointForce)force.getPointForcesList().get(1)).getForce(1);
				
				//Fx loads
				if (axvalue != 0 || bxvalue != 0) {
					po = new Point2D.Double(x1, z1);
					Point pa = da.getViewPoint(po);
					po = new Point2D.Double(x2, z2);
					Point pb = da.getViewPoint(po);
					pa.y = pa.y + 5;
					pb.y = pb.y + 5;
					Draw draw = new GridLineArrowDraw.X();
					draw.setRepresents(elm);
					((GridLineArrowDraw)draw).setBase(new LineDraw(pa, pb));
					((GridLineArrowDraw)draw).setA(a);
					((GridLineArrowDraw)draw).setB(b);
					((GridLineArrowDraw)draw).setAValue(axvalue);
					((GridLineArrowDraw)draw).setBValue(bxvalue);
					draw.setAngle(Math.toRadians(0));
					draw.setLocation(pa);
					((GridLineArrowDraw)draw).setEndLocation(pb);
					distForces.add(draw);
				}
				//Fy loads
				if (ayvalue != 0 || byvalue != 0) {
					po = new Point2D.Double(x1, z1);
					Point pa = da.getViewPoint(po);
					po = new Point2D.Double(x2, z2);
					Point pb = da.getViewPoint(po);
					Draw draw = new GridLineArrowDraw.Y();
					draw.setRepresents(elm);
					((GridLineArrowDraw)draw).setBase(new LineDraw(pa, pb));
					((GridLineArrowDraw)draw).setA(a);
					((GridLineArrowDraw)draw).setB(b);
					((GridLineArrowDraw)draw).setAValue(ayvalue);
					((GridLineArrowDraw)draw).setBValue(byvalue);
					draw.setAngle(Math.toRadians(90));
					draw.setLocation(pa);
					((GridLineArrowDraw)draw).setEndLocation(pb);
					distForces.add(draw);
				}
			}//End of distributed loads
			
		}//end of elements
		
	}
	
//*****************************************************************************
	
    public void select(Point p) {
		Draw draw;
		int index;
		
		ListIterator lns = elements.listIterator();
		while(lns.hasNext()) {
			draw = (Draw)lns.next();
			if (draw.contains(p)){
				if (draw.isSelected()) {
					draw.setSelected(false);
					index = selection.indexOf(draw.getRepresents());
					selection.remove(index);
					return;
				}else{
					draw.setSelected(true);
					selection.add(draw.getRepresents());
					return;
				}
			}
		}
		
	}
	
//*****************************************************************************
	
    public void selectAll() {
        Draw draw;
		selection.clear();
        
		ListIterator lns = elements.listIterator();
		while(lns.hasNext()) {
			draw = (Draw)lns.next();
			draw.setSelected(true);
			selection.add(draw.getRepresents());
		}
		
	}
	
//*****************************************************************************
	
    public void unSelectAll() {
        Draw draw;
		selection.clear();
        
        ListIterator pts = elements.listIterator();
        while(pts.hasNext()) {
            draw = (Draw)pts.next();
            draw.setSelected(false);
        }
		
	}

public boolean contains(IPoint3d po) {
	// TODO Auto-generated method stub
	return false;
}
	
//*****************************************************************************
}
